// VAC也就是Vacancy Mode空闲模式 ，空置模式需要手动打开灯，并在设定的时间没有动作后自动关闭灯
#include "vac_mode.h"
#include "systime.h"
#include "relay_ctrl.h"
#include "pir_sensor_detect.h"
#include "key.h"
#include "timeout_conf.h"

typedef enum
{
    VACANCY_STATE_INIT,
    VACANCY_STATE_DET,
    VACANCY_STATE_ON,
    VACANCY_STATE_OFF,
    VACANCY_STATE_UNOCCUPIED_CONFIRM,
} vacancy_state_e;

static struct
{
    timestamp_t time;
    vacancy_state_e state;
    relay_state_e relay_state;
    uint16_t unoccupied_timeout_conf;
} vacancy_mode_ctx;

void vac_mode_init(void)
{
    vacancy_mode_ctx.state = VACANCY_STATE_INIT;
    vacancy_mode_ctx.relay_state = RELAY_OFF;
    vacancy_mode_ctx.unoccupied_timeout_conf = 0;
}

void vac_mode_state_deinit(void)
{
    vacancy_mode_ctx.state = VACANCY_STATE_INIT;
}

void vac_mode_task(void)
{
    switch (vacancy_mode_ctx.state)
    {
    case VACANCY_STATE_INIT:
        pir_sensor_set_status(PIR_SENSOR_ENABLED); // 打开PIR感应
        vacancy_mode_ctx.state = VACANCY_STATE_DET;
        break;
    case VACANCY_STATE_DET:
        vacancy_mode_ctx.relay_state = get_relay_sw();
        if (vacancy_mode_ctx.relay_state == RELAY_ON)
        {
            vacancy_mode_ctx.state = VACANCY_STATE_ON;
        }
        else if (vacancy_mode_ctx.relay_state == RELAY_OFF)
        {
            vacancy_mode_ctx.state = VACANCY_STATE_OFF;
        }
        break;
    case VACANCY_STATE_ON:
        if (is_key_click())
        {
            set_relay_sw(RELAY_OFF);
            vacancy_mode_ctx.state = VACANCY_STATE_DET;
        }
        else if (!pir_sensor_is_occupied())
        {
            vacancy_mode_ctx.unoccupied_timeout_conf = timeout_conf_get_sec();
            relative_time_add_sec(&vacancy_mode_ctx.time, vacancy_mode_ctx.unoccupied_timeout_conf);
            vacancy_mode_ctx.state = VACANCY_STATE_UNOCCUPIED_CONFIRM;
        }
        break;
    case VACANCY_STATE_UNOCCUPIED_CONFIRM:
        if (pir_sensor_is_occupied())
        {
            vacancy_mode_ctx.state = VACANCY_STATE_ON;
        }
        else if (is_relative_time_timeout(&vacancy_mode_ctx.time) || is_key_click())
        {
            set_relay_sw(RELAY_OFF);
            vacancy_mode_ctx.state = VACANCY_STATE_DET;
        }
        break;
    case VACANCY_STATE_OFF:
        if (is_key_click())
        {
            set_relay_sw(RELAY_ON);
            vacancy_mode_ctx.state = VACANCY_STATE_DET;
        }
        break;

    default:
        break;
    }
}
